package com.eslag.rpc.codec;

import com.eslag.rpc.entity.RpcRequest;
import com.eslag.rpc.enumeration.PackageType;
import com.eslag.rpc.serializer.CommonSerializer;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

/**
 * 通用的编码拦截器
 *
 *  自定义协议
 *  +---------------+---------------+-----------------+-------------+
 * |  Magic Number |  Package Type | Serializer Type | Data Length |
 * |    4 bytes    |    4 bytes    |     4 bytes     |   4 bytes   |
 * +---------------+---------------+-----------------+-------------+
 * |                          Data Bytes                           |
 * |                   Length: ${Data Length}                      |
 * +---------------------------------------------------------------+
 *
 *  Magic Number ：表示一个协议包
 *  Package Type ： 标志 调用请求 还是 调用响应
 *  Serializer Type ： 实际使用的数据序列化器，服务端和客户端都应该相同
 *  Data Length ： 实际数据的长度
 *
 *
 * CommonEncoder 继承自 MessageToByteEncoder，就是把rpcQuest或者rpcResponse包装成协议包
 */
public class CommonEncoder extends MessageToByteEncoder {

    private static final int MAGIC_NUMBER = 0xCAFEBABE;

    private final CommonSerializer serializer;

    public CommonEncoder(CommonSerializer serializer) {
        this.serializer = serializer;
    }

    @Override
    protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
        out.writeInt(MAGIC_NUMBER);
        if (msg instanceof RpcRequest) {
            // 包装 RpcRequest
            out.writeInt(PackageType.REQUEST_PACK.getCode());
        } else {
            // 包装 RpcResponse
            out.writeInt(PackageType.RESPONSE_PACK.getCode());
        }
        // 写入 序列化器 的编号
        out.writeInt(serializer.getCode());
        byte[] bytes = serializer.serialize(msg);
        // 写入 实际数据的长度
        out.writeInt(bytes.length);
        // 写入 实际数据
        out.writeBytes(bytes);
    }

}